using System;
using DevExpress.Data.Filtering;
using DevExpress.Xpo;
using SmartPeople.Framework.Security.Providers.XPO;
using SmartPeople.Framework.SecuritySpace;
using SmartPeople.Framework.SecuritySpace;

namespace SmartPeople.Framework.Security.Providers.XPO
{
    internal class XPSecurityApplicationProvider : ISecurityApplicationProvider
    {
        #region CreateApplication

        /// <summary>
        /// Creates the application.
        /// </summary>
        /// <param name="securityApplicationName">Name of the security application.</param>
        /// <param name="description">The description of the security application.</param>
        /// <returns></returns>
        public ISecurityApplication CreateApplication(string securityApplicationName, string description)
        {
            XPSecurityApplication securityApplication = new XPSecurityApplication(securityApplicationName);
            //for root we assign fixed guid!
            if(securityApplicationName =="/")
            {
                string rootguid = "{D1C53875-43B4-4d3a-AB9C-BDB5A2354BDE}";
                securityApplication.GID = new Guid(rootguid);
            }
            else
            {
                //else assign a new guid!
                securityApplication.GID = Guid.NewGuid();
            }
            securityApplication.Description = description;
            securityApplication.Save();
            return securityApplication;
        }

        #endregion

        #region GetAllApplications

        /// <summary>
        /// Gets all applications.
        /// </summary>
        /// <returns>Applications</returns>
        public ISecurityApplication[] GetAllApplications()
        {
            XPCollection<XPSecurityApplication> xpCollection = new XPCollection<XPSecurityApplication>();
            ISecurityApplication[] Applications = new ISecurityApplication[xpCollection.Count];
            int length = Applications.Length;
            while (length > 0)
            {
                Applications[Applications.Length - length] = xpCollection[Applications.Length - length];
                length--;
            }
            return Applications;
        }

        #endregion

        #region GetApplication

        /// <summary>
        /// Gets the application.
        /// </summary>
        /// <param name="securityApplicationName">Name of the security application.</param>
        /// <returns></returns>
        public ISecurityApplication GetApplication(string securityApplicationName)
        {
            //basically returns a XPSecurityApplication object for name.
            GroupOperator criteria = new GroupOperator();
            criteria.Operands.Add(new BinaryOperator("Name", securityApplicationName, BinaryOperatorType.Equal));
            XPCollection xpCollection = new XPCollection(typeof (XPSecurityApplication), criteria);
            //xpCollection.Reload();
            if (xpCollection.Count == 1)
            {
                XPSecurityApplication securityApplication = (XPSecurityApplication) xpCollection[0];
                return securityApplication;
            }
            return null;
        }

        #endregion

        #region UpdateApplication

        /// <summary>
        /// Updates the application.
        /// </summary>
        /// <param name="securityApplicationName">Name of the security application.</param>
        public void UpdateApplication(ISecurityApplication securityApplicationName)
        {
            //TODO: Should we check if any values are null ?
            XPSecurityApplication securityApplication = (XPSecurityApplication) securityApplicationName;
            if (securityApplication != null)
                securityApplication.Save();
            else
                throw new ArrayTypeMismatchException("Argument should be type of XPSecurityApplication");
        }

        #endregion

        #region ApplicationExists

        /// <summary>
        /// Checks if given security application exists.
        /// </summary>
        /// <param name="securityApplicationName">Name of the security application.</param>
        /// <returns></returns>
        public bool ApplicationExists(string securityApplicationName)
        {
            ISecurityApplication securityApplication = GetApplication(securityApplicationName);
            return (securityApplication != null);
        }

        #endregion

        #region DeleteApplication(string securityApplicationName)

        /// <summary>
        /// Deletes the application.
        /// </summary>
        /// <param name="securityApplicationName">Name of the security application.</param>
        /// <returns></returns>
        public bool DeleteApplication(string securityApplicationName)
        {
            return DeleteApplication(securityApplicationName, false);
        }

        #endregion

        #region DeleteApplication

        /// <summary>
        /// Deletes the application.
        /// </summary>
        /// <param name="securityApplicationName">Name of the security application.</param>
        /// <param name="throwOnPopulatedRole">if set to <c>true</c> [throw on populated role].</param>
        /// <returns></returns>
        public bool DeleteApplication(string securityApplicationName, bool throwOnPopulatedRole)
        {
            XPSecurityApplication securityApplication = (XPSecurityApplication) GetApplication(securityApplicationName);
            if (securityApplication == null)
                return false;
            else
            {
                securityApplication.Delete();
                securityApplication.Session.PurgeDeletedObjects();
                return true;
            }
        }

        #endregion

        #region Clear

        /// <summary>
        /// Clears this instance.
        /// </summary>
        public void Clear()
        {
            XPCollection<XPSecurityApplication> xpCollection = new XPCollection<XPSecurityApplication>();
            xpCollection.Session.Delete(xpCollection);
        }

        #endregion
    }
}